"""
1、往yaml文件中写入返回结果并读取
2、断言中加入函数
3、添加内容时加入函数 例如随机数、随机姓名等
"""
import json
from utils import jsonpath_util
from utils.Custom_util import CustomMethod
from utils.YamlUtil import YamlUtil
from utils.log_util import logger
from utils.read import FileRead


class ExtractUtil:

    def __init__(self):
        # self.jsonpath_util = AssertUtil()  # 定义AssertUtil实例化，方便后续调用AssertUtil中方法
        self.yaml_util = YamlUtil()  # 定义YamlUtil实例化，方便后续调用YamlUtil中方法
        self.read = FileRead()

    def extract_data(self, res, extract):
        """
        根据extract表达式，获取接口内容并存入yaml文件
        :param res:res.json()
        :param extract:例如：$.token
        :return:
        """
        if extract:  # 如果存在extract，通过json提取到value值
            for key, expression in extract.items():
                try:
                    # 通过jsonpath提取，获取value值
                    value = jsonpath_util.extract_by_jsonpath(res, expression)
                    # 写入yaml文件
                    self.yaml_util.write_extra_yaml({key: value})
                except Exception as e:
                    logger.error(f'变量{key}写入extract.yaml失败，请检查error={e}')

    def extract_url(self, url):
        # /orders/${get_extract_value(order_id)}/
        #  判断花括号 是否在url里面，如果在进行出来；如果不在返回原本得url
        if "${" in url and "}" in url:
            return self.process_data(url)
        return url

    def extract_host(self, host):
        #  判断花括号 host是否存在，如果在提取出来；如果不在返回原本得host
        if "${" in host and "}" in host:
            return self.process_data(host)
        return host

    def process_data(self, data):
        """
        处理函数用类反射对获取到的数据和$yaml文件中数据进行处理
        :param data: 写到yaml中的$数据
        :return:
        """
        for i in range(data.count("${")):  # 对字符串 data 中 ${ 的出现次数执行循环操作
            if '${' in data and '}' in data:  # 如果${和}在data里面
                # /orders/${get_extract_value(order_id)}/
                start_index = data.index('$')
                end_index = data.index('}')
                # 获取函数中的方法
                func_full_name = data[start_index: end_index + 1]
                # 获取函数名
                func_name = data[start_index + 2: data.index('(')]
                # 获取函数中的参数名
                func_params = data[data.index('(') + 1: data.index(')')]
                # 先进行 getattr 如果self对象中存在名为func_name的属性或方法，则extract_data将被赋值为对应的属性或方法的引用；否则，extract_data将被赋值为None。
                extract_data = getattr(CustomMethod(), func_name, None)
                if extract_data is not None:
                    # 将参数拆分为列表
                    func_params = func_params.split(
                        ',') if func_params else []  # 字符串类型的func_params按逗号进行分割，生成一个列表。如果func_params为空或为None，则返回一个空列表[]
                    # 尝试将参数转换为整数，能转换则进行转换，getattr不支持函数参数为int类型，
                    func_params = [int(param) if param.isdigit() else param for param in func_params]
                    extract_data = extract_data(*func_params)  # 进行解刨参数传递
                    # print(extract_data)
                    # print(type(extract_data))
                    # 不支持函数参数为int型
                    # extract_data = getattr(self, func_name)(*func_params.split(',') if func_params else [])
                    data = data.replace(func_full_name, str(extract_data))
                    # print(type(data))
        return data

    def extract_case(self, case_info):
        str_case_info = json.dumps(case_info)  # 转换为str类型的case_info
        data = self.process_data(str_case_info)  # 调用反射处理$方法 获取结果是str类型
        # 转换为json类型
        return json.loads(data)

# if __name__ == '__main__':
#     ExtractUtil().process_data('${calculation_result5()}')